package filemd5util

import (
	"crypto/md5"
	"encoding/hex"
	"io"
	"net/http"
	"os"
)

// String 计算字符串的md5值
// s：需要计算的字符串
// result：string格式的MD5值
func String(s string) string {
	return Bytes([]byte(s))
}

// Bytes 计算bit流的md5值
// bts:字节流
// result:string格式的md5值
func Bytes(bts []byte) string {
	result := md5.Sum(bts)
	return hex.EncodeToString(result[:])
}

const (
	minSize     = 4 * 1024
	defaultSize = 40 * 1024 * 1024
	maxSize     = 100 * 1024 * 1024
)
// GetFileContentType 获取文件类型
func GetFileContentType(out *os.File) (string, error) {
	// Only the first 512 bytes are used to sniff the content type.
	buffer := make([]byte, 512)

	_, err := out.Read(buffer)
	if err != nil {
		return "", err
	}
	contentType := http.DetectContentType(buffer)

	return contentType, nil
}


//File 计算文件的md5值
func File(path string) (string, error) {
	fs, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer fs.Close()
	fi, err := fs.Stat()
	if err != nil {
		return "", err
	}
	if fi.Size() < defaultSize {
		return Reader(fs, fi.Size())
	}
	return Reader(fs)
}

//Reader 计算读数据流的md5值，buffer越大，计算速度越快，需要注意的是，buffer并不是越大越好，内存大，可适量使用大缓存
//reader：数据流
//size：buffer尺寸，默认4M，最小4K，最大100M
func Reader(reader io.Reader, size ...int64) (string, error) {
	var length int64 = 0
	if len(size) == 0 {
		length = defaultSize
	} else {
		length = size[0]
		if length < minSize {
			length = minSize
		} else if length > maxSize {
			length = maxSize
		}
	}
	hs := md5.New()
	_, err := io.CopyBuffer(hs, reader, make([]byte, length))
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(hs.Sum(nil)[:]), nil
}
